#ifndef OBSERVER_HPP_
#define OBSERVER_HPP_

#include "Subject.hpp"

class CurrentConditionDisplay : public Observer, Display
{
private:
  float _temp;
  float _humidity;
  float _pressure;
  Subject* _weatherData;

public:
  CurrentConditionDisplay(Subject* weatherData)
    :_temp(0), _humidity(0), _pressure(0), _weatherData(weatherData)
  {
    Register();
  }

  void Register()
  {
    _weatherData->RegisterObserver(this);
  }
  
  void Remove()
  {
    _weatherData->RemoveObserver(this);
  }

  // 天气数据更新
  void Update(float temp, float humidity, float pressure)
  {
    _temp = temp;
    _humidity = humidity;
    _pressure = pressure;

    Print();
  }

  // 天气数据打印
  void Print()
  {
    std::cout << "############################当前状况############################" << std::endl;
    std::cout << "温度：" << _temp << "℃" << std::endl;
    std::cout << "湿度：" << _humidity << "%" << std::endl;
    std::cout << "气压：" << _pressure << "kPa" << std::endl;
  }
};

class StatisticsDisplay : public Observer, Display
{
private:
  float _aveTemp;
  float _lowTemp;
  float _highTemp;
  Subject* _weatherData;

public:
  StatisticsDisplay(Subject* weatherData)
      : _aveTemp(0), _lowTemp(0), _highTemp(0), _weatherData(weatherData)
  {
    Register();
  }

  void Register()
  {
    _weatherData->RegisterObserver(this);
  }
  
  void Remove()
  {
    _weatherData->RemoveObserver(this);
  }

  void Update(float temp, float humidity, float pressure)
  {
    if (_aveTemp == 0)
    {
      _aveTemp = temp;
      _lowTemp = temp;
      _highTemp = temp;
    }
    else
    {
      _aveTemp = (_aveTemp + temp) / 2;
      _lowTemp = (rand() % 10 - 10) + _aveTemp;
      _highTemp = (rand() % 10) + _aveTemp;
    }

    Print();
  }

  void Print()
  {
    std::cout << "############################气象统计############################" << std::endl;
    std::cout << "平均气温：" << _aveTemp << "℃" << std::endl;
    std::cout << "最低气温：" << _lowTemp << "℃" << std::endl;
    std::cout << "最高气温：" << _highTemp << "℃" << std::endl;
  }
  ~StatisticsDisplay() {}
};

class ForecastDisplay : public Observer, Display
{
private:
  float _temp;
  float _humidity;
  float _pressure;
  std::vector<std::string> _forecast;
  Subject* _weatherData;

  void InitForecast()
  {
    _forecast.push_back("⛅");
    _forecast.push_back("☔");
    _forecast.push_back("🌞");
    _forecast.push_back("☀️");
    _forecast.push_back("🌧️");
    _forecast.push_back("☁️");
    _forecast.push_back("🌩️");
    _forecast.push_back("🌪️");
    _forecast.push_back("☂️");
    _forecast.push_back("🌂");
    _forecast.push_back("❄️");
    _forecast.push_back("⛱️");
    _forecast.push_back("💧");
    _forecast.push_back("🌊");
    _forecast.push_back("☃️");
    _forecast.push_back("⚡");
    _forecast.push_back("🔥");
    _forecast.push_back("🌨️");
  }

public:
  ForecastDisplay(Subject* WeatherData)
      : _temp(0), _humidity(0), _pressure(0), _weatherData(WeatherData)
  {
    InitForecast();
    Register();
  }

  void Register()
  {
    _weatherData->RegisterObserver(this);
  }
  
  void Remove()
  {
    _weatherData->RemoveObserver(this);
  }

  void Update(float temp, float humidity, float pressure)
  {
    _temp = temp;
    _humidity = humidity;
    _pressure = pressure;

    Print();
  }

  void Print()
  {
    std::cout << "############################天气预报############################" << std::endl;
    std::cout << "预计明天天气为: " << _forecast[rand() % _forecast.size()] << std::endl;
  }
};

#endif
